package eMdP.classesBasiques;

import com.jme.bounding.BoundingBox;
import com.jme.intersection.PickData;
import com.jme.intersection.PickResults;
import com.jme.intersection.TrianglePickResults;
import com.jme.math.FastMath;
import com.jme.math.Quaternion;
import com.jme.math.Ray;
import com.jme.math.Vector3f;
import com.jme.scene.Spatial;
import com.jme.util.Timer;
import com.jmex.physics.DynamicPhysicsNode;
import com.jmex.physics.PhysicsSpace;
import com.jmex.physics.StaticPhysicsNode;

import eMdP.gestors.GestorConstants;

/**
 * PersonatgeNJ és una herencia de Personatge que controla el moviment del jugador al joc. A part
 * de tots els atributs de la classe Personatge, la classe PersonatgeNJ té l'atribut de "IA", que controla la
 * intel·ligéncia Artificial del PNJ. 
 * 
 * @author Peppino Coorp.
 */

public class PersonatgeNJ extends Personatge{
	private static final long serialVersionUID = 1L;
	
	//private static final Logger logger = Logger.getLogger(Partida.class.getName());
	
	private float angle;
	
	// Variables que defineixen les seves característiques físiques 
	private float visio;
	
	public PersonatgeNJ(String nom, float visio, PhysicsSpace espaiFisic, float força, int id){
		super(nom,"","",GestorConstants.DIRECCIO_PNJ,espaiFisic,força,id);
		setIdJugador(-1);
		this.visio = visio;
		this.angle=0;
	}
	
	/* ----------------------------------  Fi dels GETTES/SETTERS  -------------------------------------------- */
	
	/**
	 * Metode que retorna cert si és un PErsonatge jugador i fals altrament
	 * @return socPersonatge
	 */
	public boolean socPersonatge(){
		boolean socPersonatge = false;
		return socPersonatge;
	}
	
	/**
	 * @param posicio Vector3f que conté la nova direcció del nodeEstatic
	 */
	public void setLocalTranslation(Vector3f posicio){
		super.setLocalTranslation(posicio);
	}
	
	/**
	 * @return La posició Local que està el node Estàtic
	 */
	public Vector3f getLocalTranslation(){
		return super.getLocalTranslation();
	}
	
	/**
	 * @param posicio Vector3f que conté la nova direcció del nodeEstatic
	 */
	public void setLocalRotation(Quaternion posicio){
		super.setLocalRotation(posicio);
	}
	
	/**
	 * @return La posició Local que està el node Estàtic
	 */
	public Quaternion getLocalRotation(){
		return super.getLocalRotation();
	}
	
		
	private void buscarAlVoltant(Vector3f origen,float temps){
		
		//Inicialitzem el retorn, cap on mira inicialment
		Quaternion direccio = new Quaternion(this.getLocalRotation());
		PickResults results = llançarRaig(origen,this.getLocalRotation().getRotationColumn(2, new Vector3f()));
		boolean trobat = (hiHaJugadorDavant(results,temps));
		//int i = 0;
		
		/* Fem una cerca desde maxEsquerra fins a maxDreta si trobem el jugador parem i retornem la direccio */
		//while(this.maxEsquerra+i < this.maxDreta && !trobat){
			Quaternion rotQuat = new Quaternion();
			rotQuat.set(this.getLocalRotation());
			rotQuat.fromAngleAxis(FastMath.DEG_TO_RAD*(this.angle), new Vector3f(0, 1, 0));
			
			results = llançarRaig(origen,rotQuat.getRotationColumn(2, new Vector3f()));
			
			if(hiHaJugadorDavant(results,temps)){
				trobat=true;
				direccio.set(rotQuat);
				this.getLocalRotation().set(direccio);
				
			}
			
			this.angle++;
			
		//}
		if(trobat){
			this.getLocalTranslation().addLocal(capOnMira().multLocal(20*Timer.getTimer().getTimePerFrame()));
			//System.out.println("Trobem el jugador:");
		}
			
	}
	
	/**
	 * Métode que li passem un PickResults (conté totes les col·lisions d'un raig), i busca si a la segona posició hi ha el jugador. Mirem la segona
	 * perqué a la primera hi ha d'haver la caixa de l'enemig, per tant la segona ha de ser el Jugador.
	 * 
	 * @return trobat Cert si hi ha el jugador i no està immune ni bloquejat, Fals altrament.
	 */
	private boolean hiHaJugadorDavant( PickResults results,float temps){
		
		boolean trobat = false;
		
		if(results.getNumber() > 1) {
			
			/* Agafem la col·lisio 1, perqué la 0 conté el model del pnj */
			PickData closest = results.getPickData(1); //Com que estan ordenats els objectes del Ray, el 1er és l'enemig i si el 2on es Jugador perseguim!
			//if(closest.getDistance()<visio && esFillDUnPersonatge(closest.getTargetMesh(),temps)){
			//if(esFillDUnPersonatge(closest.getTargetMesh(),temps)){
			if(closest.getTargetMesh().getParent().getName().contains("Personatge")){
				trobat=!((Personatge)closest.getTargetMesh().getParent().getParent()).estaBloquejat(temps);	
			}
				
		}
		return trobat;
	}
	
	/**
	 * Llença un raig que passa per el punt origen amb la direccio passada per parametres. Retorna un PickResults que conté totes les col·lisions
	 * obtingudes i ordenades per ordre de proximitat
	 * 
	 * @param origen Vector3f que indica el punt d'origen des de on llancem el raig.
	 * @param direccio Vector3f La direcció en que llancem el raig
	 * 
	 * @return results PickResults que conté totes les col·lisions que ha fet el raig.
	 */
	private PickResults llançarRaig(Vector3f origen,Vector3f direccio){
		
		Ray ray = new Ray(origen, direccio);
		PickResults results = new TrianglePickResults();
		results.setCheckDistance(true);
		this.getParent().findPick(ray,results);
		
		return results;
	}
	
	/**
	 * El PersoantgeNJ està quiet mirant al seu voltant, i segons l'atribut IA, veu més lluny o més aprop. Si et veu et persegueix.
	 * Métode per controlar els moviments del PersonatgeNJ. Consisteix en anar llançant Rays per veure't, si et veu, i estas a una 
	 * distància inferior a IA et persegueix.
	 */
	public void actualitzar(float temps){
		// Actualitzem la força per mantenir dempeus el PNJ
		update(Timer.getTimer().getTimePerFrame());
		// Comprovem que no estigui bloquejat
		if(!this.estaBloquejat(temps)){
			Vector3f origen = new Vector3f(this.getLocalTranslation());
			origen.setY(0.6f);
			buscarAlVoltant(origen,temps);
		}
		this.netejarFisiques();
		
	}

}
